﻿

namespace LxCFD
{
    public class ConnectWallTwoSide : ConnectWallBase
    {
        protected Value1Base<double> I_Gamma;
        protected Value1Base<double> Thickness;
        public void setConnect(Value1Base<double> Tau, Value1Base<double> Thickness, ValueBase<double> S, EquationBase OMatrix, EquationBase NMatrix)
        {
            setArray_2(S, OMatrix, NMatrix);

            this.I_Gamma = Tau;
            this.Thickness = Thickness;
        }
        public override void SetAb_Step1(int taskIndex)
        {
            if (S is Value1Base<double> s1)
            {
                if (s1.IsEqual0()) //s1 is Value1Const s1c && s1c.number == 0
                {
                    InnerIndex.FaceIDs.GetSeg(out int i1, out int endp1, taskIndex);
                    for (; i1 < endp1; i1++)
                    {
                        ref PairMatrix ab = ref ADLUb[i1];
                        ab.b2 = ab.b3 = 0;
                        ab.a22 = ab.a33 = 0;

                        int ofid = i1 + deltaOFaceId;
                        int nfid = i1 + deltaNFaceId;
                        setAb_TwoSideWall(ref ab, ofid, ref O_Faces[ofid], nfid, ref N_Faces[nfid]);
                    }
                }
                else
                {
                    InnerIndex.FaceIDs.GetSeg(out int i1, out int endp1, taskIndex);
                    for (; i1 < endp1; i1++)
                    {
                        ref PairMatrix ab = ref ADLUb[i1];
                        int ofid = i1 + deltaOFaceId;
                        ref FvFace oface = ref O_Faces[ofid];
                        double s = s1.GetFaceValue(ofid) * oface.Area / 2;
                        ab.b2 = ab.b3 = s;
                        ab.a22 = ab.a33 = 0;

                        int nfid = i1 + deltaNFaceId;
                        setAb_TwoSideWall(ref ab, ofid, ref oface, nfid, ref N_Faces[nfid]);
                    }
                }
            }
            else if (S is Value2Base<double> s2)
            {
                InnerIndex.FaceIDs.GetSeg(out int i1, out int endp1, taskIndex);
                for (; i1 < endp1; i1++)
                {
                    ref PairMatrix ab = ref ADLUb[i1];
                    int ofid = i1 + deltaOFaceId;
                    ref FvFace oface = ref O_Faces[ofid];
                    double halfArea = oface.Area / 2;
                    s2.GetFaceValue(out double sou_ad, out double sou_b, ofid);
                    ab.b2 = ab.b3 = sou_b * halfArea;
                    ab.a22 = ab.a33 = -sou_ad * halfArea;

                    int nfid = i1 + deltaNFaceId;
                    setAb_TwoSideWall(ref ab, ofid, ref oface, nfid, ref N_Faces[nfid]);
                }
            }
            else
            {
                LxConsole.Error(string.Format($"接触面{Contact.name}源项无法识别"));
            }
        }
        protected void setAb_TwoSideWall(ref PairMatrix ab, int ofid, ref FvFace oface, int nfid, ref FvFace nface)
        {
            double ogamma = O_Gamma.GetFaceValue(ofid);
            double ogg = ogamma * oface.gDiff;
            double ofacecor = ogamma * oface.CalNonOrthogonalityCorrection_bound(out double ocor_a, out double ocor_b, O_grad, O_x, O_Cells);
            ocor_a *= ogamma;
            ocor_b *= ogamma;

            double ngamma = N_Gamma.GetFaceValue(nfid);
            double ngg = ngamma * nface.gDiff;
            double nfacecor = ngamma * nface.CalNonOrthogonalityCorrection_bound(out double ncor_a, out double ncor_b, N_grad, N_x, N_Cells);
            ncor_a *= ngamma;
            ncor_b *= ngamma;

            double igg = I_Gamma.GetFaceValue(ofid) * oface.Area / Thickness.GetFaceValue(ofid);

            ab.a11 = ogg; ab.a12 = -ogg; ab.b1 = ofacecor;
            ab.a44 = ngg; ab.a43 = -ngg; ab.b4 = nfacecor;
            ab.a23 = ab.a32 = -igg;
            ab.a22 += ogg + igg + ocor_a; ab.a21 = -ogg - ocor_a; ab.b2 += -ocor_b;
            ab.a33 += ngg + igg + ncor_a; ab.a34 = -ngg - ncor_a; ab.b3 += -ncor_b;
            ab.Eliminate_a23a32();
            ab.Eliminate_a12a43();
            setAb_ONALU(ref ab, ofid, nfid);
        }
        public override void Update_x_Bound(int taskIndex)
        {
            InnerIndex.FaceIDs.GetSeg(out int i1, out int endp1, taskIndex);
            for (; i1 < endp1; i1++)
            {
                ref FvPair pair = ref Pairs[i1];
                ref PairMatrix ab = ref ADLUb[i1];
                double x1 = O_x[pair.O_InnCell];
                double x4 = N_x[pair.N_InnCell];
                O_x[pair.O_Cell] = (ab.b2 - ab.a21 * x1 - ab.a24 * x4) / ab.a22;
                N_x[pair.N_Cell] = (ab.b3 - ab.a31 * x1 - ab.a34 * x4) / ab.a33;
            }
        }
    }
}

//iniSource(taskIndex);
//InnerIndex.FaceIDs.GetSeg(out int i1, out int endp1, taskIndex);
//for (; i1 < endp1; i1++)
//{
//    int ofid = i1 + deltaOFaceId;
//    ref Face oface = ref O_faces[ofid];
//    double ogamma = O_Gamma.getFaceValue(ofid);
//    double ogg = ogamma * oface.gDiff;
//    double ofacecor = ogamma * oface.CalNonOrthogonalityCorrection_bound(out double ocor_a, out double ocor_b, O_grad, O_x, O_cells);
//    ocor_a *= ogamma;
//    ocor_b *= ogamma;

//    int nfid = i1 + deltaNFaceId;
//    ref Face nface = ref N_faces[nfid];
//    double ngamma = N_Gamma.getFaceValue(nfid);
//    double ngg = ngamma * nface.gDiff;
//    double nfacecor = ngamma * nface.CalNonOrthogonalityCorrection_bound(out double ncor_a, out double ncor_b, N_grad, N_x, N_cells);
//    ncor_a *= ngamma;
//    ncor_b *= ngamma;

//    double igg = I_Gamma.getFaceValue(ofid) * O_faces[ofid].Area / Thickness.getFaceValue(ofid);

//    ref PairMatrixAb ab = ref ADLUb[i1];
//    ab.a11 = ogg; ab.a12 = -ogg; ab.b1 = ofacecor;
//    ab.a44 = ngg; ab.a43 = -ngg; ab.b4 = nfacecor;
//    ab.a23 = ab.a32 = -igg;
//    ab.a22 += ogg + igg + ocor_a; ab.a21 = -ogg - ocor_a; ab.b2 += -ocor_b;
//    ab.a33 += ngg + igg + ncor_a; ab.a34 = -ngg - ncor_a; ab.b3 += -ncor_b;
//    ab.Eliminate_a23a32();
//    ab.Eliminate_a12a43();
//    O_ALUN[ofid] = -ab.a11;
//    O_ALUO[ofid] = 1;
//    O_bFaceCommon[ofid] = ab.b1;
//    N_ALUN[nfid] = -ab.a44;
//    N_ALUO[nfid] = 1;
//    N_bFaceCommon[nfid] = ab.b4;
//}
#region 备份
//InnerIndex.FaceIdx.GetSeg(out int i1, out int endp1, taskIndex);
//for (; i1 < endp1; i1++)
//{
//    int ofid = i1 + deltaOFaceId;
//    ref Face oface = ref O_faces[ofid];
//    double ogamma = O_Gamma.getFaceValue(ofid);
//    double ogg = ogamma * oface.gDiff;
//    double ofacecor = ogamma * oface.calNonOrthogonalityCorrection_bound(out double ocor_a, out double ocor_b, O_grad, O_x, O_cells);
//    ocor_a *= ogamma;
//    ocor_b *= ogamma;
//    //O_ALUO[ofid] = O_ALUN[ofid] = -ogg;
//    //O_bFaceCommon[ofid] = ofacecor;
//    //O_b[oface.NeighborCellIndex] = -ocor_b;

//    int nfid = i1 + deltaNFaceId;
//    ref Face nface = ref N_faces[nfid];
//    double ngamma = N_Gamma.getFaceValue(nfid);
//    double ngg = ngamma * nface.gDiff;
//    double nfacecor = ngamma * nface.calNonOrthogonalityCorrection_bound(out double ncor_a, out double ncor_b, N_grad, N_x, N_cells);
//    ncor_a *= ngamma;
//    ncor_b *= ngamma;
//    //N_ALUO[nfid] = N_ALUN[nfid] = -ngg;
//    //N_bFaceCommon[nfid] = nfacecor;
//    //N_b[nface.NeighborCellIndex] = -ncor_b;

//    double igg = I_Gamma.getFaceValue(ofid) * O_faces[ofid].Area / Thickness.getFaceValue(ofid);
//    //A_LU_Diff[i1] = -igg;
//    //O_ADiag[oface.NeighborCellIndex] = ogg + igg + ocor_a;
//    //N_ADiag[nface.NeighborCellIndex] = ngg + igg + ncor_a;

//    ref PairMatrixAb ab = ref ADLUb[i1];
//    ab.a12 = ab.a21 = -ogg;
//    ab.a43 = ab.a34 = -ngg;
//    ab.a23 = ab.a32 = -igg;
//    ab.a11 = ogg; ab.b1 = ofacecor;
//    ab.a44 = ngg; ab.b4 = nfacecor;
//    ab.a22 += ogg + igg + ocor_a; ab.b2 += -ocor_b;
//    ab.a33 += ngg + igg + ncor_a; ab.b3 += -ncor_b;
//    ab.Eliminate_a23a32();
//    ab.Eliminate_a12a43();
//    O_ALUN[ofid] = -ab.a11;
//    O_ALUO[ofid] = 1;
//    O_bFaceCommon[ofid] = ab.b1;
//    N_ALUN[nfid] = -ab.a44;
//    N_ALUO[nfid] = 1;
//    N_bFaceCommon[nfid] = ab.b4;
//}
#endregion
//protected double[] A_LU_Diff;
//protected double ownerRelaxFactor = 1;
//protected double neighborRelaxFactor = 1;
//MathTool.IfArrayNullCreate(ref A_LU_Diff, InnerIndex.FaceIdx.GetCount());
//this.ownerRelaxFactor = O_Matrix.relaxFactor;
//this.neighborRelaxFactor = N_Matrix.relaxFactor;

//public override void Relax(int taskIndex)
//{
//    double relax1 = 1 - ownerRelaxFactor;
//    double relax2 = 1 - neighborRelaxFactor;
//    InnerIndex.CellIdx.GetSeg(out int i1, out int endp1, taskIndex);
//    for (; i1 < endp1; i1++)
//    {
//        int ocid = i1 + deltaOCellId;
//        ref double adiag = ref O_ADiag[ocid];
//        adiag /= ownerRelaxFactor;
//        O_b[ocid] += relax1 * adiag * O_x[ocid];

//        int ncid = i1 + deltaNCellId;
//        adiag = ref N_ADiag[ncid];
//        adiag /= neighborRelaxFactor;
//        N_b[ncid] += relax2 * adiag * N_x[ncid];
//    }

//}
//public override void CalByGS(int taskIndex)
//{
//    cal_x(O_x, N_x, O_x, N_x, taskIndex);
//}
//public override void CalByJacobi_Step1(int taskIndex)
//{
//    cal_x(O_x, N_x, O_xCommon, N_xCommon, taskIndex);
//}

//public override void CalByJacobi_Step2(int taskIndex)
//{
//    cal_x(O_xCommon, N_xCommon, O_x, N_x, taskIndex);
//}
//protected void cal_x(double[] O_from, double[] N_from, double[] O_to, double[] N_to, int taskIndex)
//{
//    InnerIndex.FaceIdx.GetSeg(out int i1, out int endp1, taskIndex);
//    for (; i1 < endp1; i1++)
//    {
//        ref Mesh.Pair pair = ref Pairs[i1];
//        double alui = A_LU_Diff[i1];
//        O_to[pair.O_Cell] = (O_b[pair.O_Cell]
//            - O_ALUN[pair.O_Face] * O_from[pair.O_InnCell]
//            - alui * N_from[pair.N_Cell]
//            ) / O_ADiag[pair.O_Cell];
//        N_to[pair.N_Cell] = (N_b[pair.N_Cell]
//             - N_ALUN[pair.N_Face] * N_from[pair.N_InnCell]
//             - alui * O_from[pair.O_Cell]
//              ) / N_ADiag[pair.N_Cell];
//    }
//}
#region 接口IPassDataToCoarserContact
//public override void SendRestrict_ALUr(out double A_Diag, out double OZone_A_LU_O, out double OZone_A_LU_N, out double NZone_A_LU_O, out double NZone_A_LU_N, ref MGMesh.Pair CoarsePair)
//{
//    double Atemp = 0, rtemp = 0, aluo = 0, alun = 0;
//    foreach (int fpair in CoarsePair.FinePairs)
//    {
//        ref Mesh.Pair pair = ref Pairs[fpair];
//        double xo = O_x[pair.O_Cell];
//        double ad = O_ADiag[pair.O_Cell];
//        double alu = O_ALUN[pair.O_Face];
//        Atemp += ad;
//        rtemp += O_b[pair.O_Cell]
//            - alu * O_x[pair.O_InnCell]
//            - ad * xo;
//        aluo += alu;

//        double xn = N_x[pair.N_Cell];
//        ad = N_ADiag[pair.N_Cell];
//        alu = N_ALUN[pair.N_Face];
//        Atemp += ad;
//        rtemp += N_b[pair.N_Cell]
//            - alu * N_x[pair.N_InnCell]
//            - ad * xn;
//        alun += alu;

//        alu = A_LU_Diff[fpair];
//        Atemp += alu * 2;////////之前没减也能算？？？？？
//        rtemp -= A_LU_Diff[fpair] * (xo + xn);
//    }
//    A_Diag = Atemp;
//    CoarsePair.r = rtemp;
//    OZone_A_LU_O = OZone_A_LU_N = aluo;
//    NZone_A_LU_O = NZone_A_LU_N = alun;
//}
//public override void SendRestrict_r(ref MGMesh.Pair CoarsePair)
//{
//    double rtemp = 0;
//    foreach (int fpair in CoarsePair.FinePairs)
//    {
//        ref Mesh.Pair pair = ref Pairs[fpair];

//        double xo = O_x[pair.O_Cell];
//        rtemp += O_b[pair.O_Cell]
//            - O_ALUN[pair.O_Face] * O_x[pair.O_InnCell]
//            - O_ADiag[pair.O_Cell] * xo;

//        double xn = N_x[pair.N_Cell];
//        rtemp += N_b[pair.N_Cell]
//            - N_ALUN[pair.N_Face] * N_x[pair.N_InnCell]
//            - N_ADiag[pair.N_Cell] * xn;

//        rtemp -= A_LU_Diff[fpair] * (xo + xn);

//    }
//    CoarsePair.r = rtemp;
//}
#endregion
//public void pass_A_r_owner_ToCoarser(out double A_owner, ref MGMesh.Cell ownerCoarser)
//{
//    double Atemp = 0;
//    double rtemp = 0;
//    foreach (int ocell in ownerCoarser.FineCells)
//    {
//        int oface = O_cells[ocell].CellFacesAsN[0];
//        int nface = oface + deltaFaceIndex;
//        int ncell = ocell + deltaCellIndex;
//        double xo = O_x[ocell];
//        double xn = N_x[ncell];

//        double atemp = O_A_Diag[ocell];
//        Atemp += atemp;
//        rtemp += O_b[ocell]
//            - O_A_LU[oface] * O_x[O_faces[oface].OwnerCellIndex]
//            - atemp * xo;

//        atemp = N_A_Diag[ncell];
//        Atemp += atemp;
//        rtemp += N_b[ncell]
//            - N_A_LU[nface] * N_x[N_faces[nface].OwnerCellIndex]
//            - atemp * xn;
//        rtemp -= A_LU_Diff[oface + deltaALUIndex] * (xo + xn);
//    }
//    A_owner = Atemp;
//    ownerCoarser.r = rtemp;
//}
//void IPassDataToCoarserContact.pass_r_owner_ToCoarser(ref MGMesh.Cell ownerCoarser)
//{
//    double rtemp = 0;
//    foreach (int ocell in ownerCoarser.FineCells)
//    {
//        int oface = O_cells[ocell].CellFacesAsN[0];
//        int nface = oface + deltaFaceIndex;
//        int ncell = ocell + deltaCellIndex;
//        double xo = O_x[ocell];
//        double xn = N_x[ncell];

//        double atemp = O_A_Diag[ocell];
//        rtemp += O_b[ocell]
//            - O_A_LU[oface] * O_x[O_faces[oface].OwnerCellIndex]
//            - atemp * xo;

//        atemp = N_A_Diag[ncell];
//        rtemp += N_b[ncell]
//            - N_A_LU[nface] * N_x[N_faces[nface].OwnerCellIndex]
//            - atemp * xn;
//        rtemp -= A_LU_Diff[oface + deltaALUIndex] * (xo + xn);
//    }
//    ownerCoarser.r = rtemp;
//}
//public void SetAb_Step2(int taskIndex)
//{
//    //if (S is Value1Base s1)
//    //{
//    //    if (s1 is Value1Const s1c && s1c.number == 0) return;
//    //    O_Index.FaceIdx.GetSeg(out int i1, out int endp1, taskIndex);
//    //    for (; i1 < endp1; i1++)
//    //    {
//    //        ref Face oface = ref O_faces[i1];
//    //        double s = s1.getFaceValue(i1) * oface.Area / 2;
//    //        O_b[oface.NeighborCellIndex] += s;
//    //        int ncell = oface.NeighborCellIndex + NCellBaseO;
//    //        N_b[ncell] += s;
//    //    }
//    //}
//    //else if (S is Value2Base s2)
//    //{
//    //    O_Index.FaceIdx.GetSeg(out int i1, out int endp1, taskIndex);
//    //    for (; i1 < endp1; i1++)
//    //    {
//    //        ref Face oface = ref O_faces[i1];
//    //        s2.getFaceValue(out double sou_ad, out double sou_b, i1);
//    //        sou_ad = sou_ad * oface.Area / 2;
//    //        sou_b = sou_b * oface.Area / 2;
//    //        O_A_Diag[oface.NeighborCellIndex] -= sou_ad;
//    //        O_b[oface.NeighborCellIndex] += sou_b;
//    //        int ncell = oface.NeighborCellIndex + NCellBaseO;
//    //        N_A_Diag[ncell] -= sou_ad;
//    //        N_b[ncell] += sou_b;
//    //    }
//    //}
//    //else
//    //{
//    //    LxConsole.AddLine(LogTypes.错误, string.Format($"接触面{contact.name}源项无法识别"));
//    //}
//}
//public void Relax(int taskIndex)
//{
//    double relax1 = 1 - ownerRelaxFactor;
//    double relax2 = 1 - neighborRelaxFactor;
//    O_Index.CellIdx.GetSeg(out int i1, out int endp1, taskIndex);
//    for (; i1 < endp1; i1++)
//    {
//        ref double adiag = ref O_A_Diag[i1];
//        adiag /= ownerRelaxFactor;
//        O_b[i1] += relax1 * adiag * O_x[i1];
//        int ncell = i1 + NCellBaseO;
//        adiag = ref N_A_Diag[ncell];
//        adiag /= neighborRelaxFactor;
//        N_b[ncell] += relax2 * adiag * N_x[ncell];
//    }
//}
//public void Cal_x_GS(int taskIndex)
//{
//    cal_x(O_x, N_x, O_x, N_x, taskIndex);
//}
//public void Cal_x_JacobiStep1(int taskIndex)
//{
//    cal_x(O_x, N_x, O_xCommon, N_xCommon, taskIndex);
//}

//public void Cal_x_JacobiStep2(int taskIndex)
//{
//    cal_x(O_xCommon, N_xCommon, O_x, N_x, taskIndex);
//}
//protected void cal_x(double[] O_from, double[] N_from, double[] O_to, double[] N_to, int taskIndex)
//{
//    O_Index.FaceIdx.GetSeg(out int oface, out int endp1, taskIndex);
//    for (; oface < endp1; oface++)
//    {
//        int ocell = O_faces[oface].NeighborCellIndex;
//        int nface = oface + NFaceBaseO;
//        int ncell = ocell + NCellBaseO;
//        double alu = A_LU_Diff[oface + IFaceBaseO];
//        O_to[ocell] = (O_b[ocell]
//            - O_A_LU_N[oface] * O_from[O_faces[oface].OwnerCellIndex]
//            - alu * N_from[ncell]
//            ) / O_A_Diag[ocell];
//        N_to[ncell] = (N_b[ncell]
//             - N_A_LU_N[nface] * N_from[N_faces[nface].OwnerCellIndex]
//             - alu * O_from[ocell]
//              ) / N_A_Diag[ncell];
//    }
//}
//O_Index.FaceIdx.GetSeg(out int ofid, out int endp1, taskIndex);
//int nfid = ofid + NFaceBaseO, iid = ofid + IFaceBaseO;
//MatrixToEliminateBound mtool = new MatrixToEliminateBound();
//ref double alun = ref Local_A_LU_N[iid];
//ref double aluo = ref Local_A_LU_O[iid];
//ref double alui = ref Local_A_LU_Diff[iid];

//ref Face oface = ref O_faces[ofid];
//double ogamma = O_Gamma.getFaceValue(ofid);
//double ogg = ogamma * oface.gDiff;
//double ofacecor = ogamma * oface.calNonOrthogonalityCorrection_bound(out double ocor_a, out double ocor_b, O_grad, O_x, O_cells);
//ocor_a *= ogamma;
//ocor_b *= ogamma;
//aluo = -ogg;
////O_A_LU_N[ofid] = -ogg;
////O_bFaceCommon[ofid] = ofacecor;
////O_b[oface.NeighborCellIndex] = -ocor_b;

//ref Face nface = ref N_faces[nfid];
//double ngamma = N_Gamma.getFaceValue(nfid);
//double ngg = ngamma * nface.gDiff;
//double nfacecor = ngamma * nface.calNonOrthogonalityCorrection_bound(out double ncor_a, out double ncor_b, N_grad, N_x, N_cells);
//ncor_a *= ngamma;
//ncor_b *= ngamma;
////N_A_LU_N[nfid] = -ngg;
////N_bFaceCommon[nfid] = nfacecor;
////N_b[nface.NeighborCellIndex] = -ncor_b;

//ref double oadiag = ref O_A_Diag[oface.NeighborCellIndex];
//ref double ob = ref O_b[oface.NeighborCellIndex];
//int ncell = oface.NeighborCellIndex + NCellBaseO;
//ref double nadiag = ref N_A_Diag[ncell];
//ref double nb = ref N_b[ncell];
//ob += -ocor_b;
//nb += -ncor_b;

//double igg = I_Gamma.getFaceValue(ofid) * O_faces[ofid].Area / Thickness.getFaceValue(ofid);
//alui = -igg;
//oadiag = ogg + igg + ocor_a;
//nadiag = ngg + igg + ncor_a;

////mtool.r1.Set();
//O_bFaceCommon[ofid] = ofacecor;
//N_bFaceCommon[nfid] = nfacecor;
//public void SetAb_(int taskIndex)
//{
//    InnerIndex.FaceIdx.GetSeg(out int iid, out int endp1, taskIndex);
//    MatrixToEliminateBound mtool = new MatrixToEliminateBound();
//    for (; iid < endp1; iid++)
//    {
//        int ofid = iid + deltaOFaceId;
//        int nfid = iid + deltaNFaceId;
//        ref double alun = ref Local_A_LU_N[iid];
//        ref double aluo = ref Local_A_LU_O[iid];
//        ref double alui = ref Local_A_LU_Diff[iid];

//        ref Face oface = ref O_faces[ofid];
//        double ogamma = O_Gamma.getFaceValue(ofid);
//        double ogg = ogamma * oface.gDiff;
//        double ofacecor = ogamma * oface.calNonOrthogonalityCorrection_bound(out double ocor_a, out double ocor_b, O_grad, O_x, O_cells);
//        ocor_a *= ogamma;
//        ocor_b *= ogamma;
//        aluo = -ogg;

//        ref Face nface = ref N_faces[nfid];
//        double ngamma = N_Gamma.getFaceValue(nfid);
//        double ngg = ngamma * nface.gDiff;
//        double nfacecor = ngamma * nface.calNonOrthogonalityCorrection_bound(out double ncor_a, out double ncor_b, N_grad, N_x, N_cells);
//        ncor_a *= ngamma;
//        ncor_b *= ngamma;
//        alun = -ngg;

//        ref double oadiag = ref LocalO_A_Diag[iid];
//        ref double ob = ref LocalO_b[iid];
//        ref double nadiag = ref LocalN_A_Diag[iid];
//        ref double nb = ref LocalN_b[iid];
//        ob += -ocor_b;
//        nb += -ncor_b;

//        double igg = I_Gamma.getFaceValue(ofid) * oface.Area / Thickness.getFaceValue(ofid);
//        alui = -igg;
//        oadiag = ogg + igg + ocor_a;
//        nadiag = ngg + igg + ncor_a;


//        O_bFaceCommon[ofid] = ofacecor;
//        N_bFaceCommon[nfid] = nfacecor;

//        O_A_LU_O[ofid] = N_A_LU_O[nfid] = 1;//这是与对面区域的系数
//    }
//}
//public struct MatrixToEliminateBound
//{
//    public A4b1 r1;
//    public A4b1 r2;
//    public A4b1 r3;
//    public A4b1 r4;
//    public void Eliminate()
//    {
//        A4b1 tool = r2;
//        tool.Minus(r2.a3 / r3.a3, r3);
//        r1.Minus(r1.a2 / tool.a2, tool);
//        tool = r3;
//        tool.Minus(r3.a2 / r2.a2, r2);
//        r4.Minus(r4.a3 / tool.a3, tool);
//    }
//    public void Print()
//    {
//        Console.WriteLine(r1);
//        Console.WriteLine(r2);
//        Console.WriteLine(r3);
//        Console.WriteLine(r4);
//    }
//}
//public struct A4b1
//{
//    public double a1;
//    public double a2;
//    public double a3;
//    public double a4;
//    public double b;
//    public void Set(double a1, double a2, double a3, double a4, double b)
//    {
//        this.a1 = a1;
//        this.a2 = a2;
//        this.a3 = a3;
//        this.a4 = a4;
//        this.b = b;
//    }
//    public void Multiply(double d)
//    {
//        a1 *= d;
//        a2 *= d;
//        a3 *= d;
//        a4 *= d;
//        b *= d;
//    }
//    public void Minus(double d, A4b1 ab)
//    {
//        a1 -= d * ab.a1;
//        a2 -= d * ab.a2;
//        a3 -= d * ab.a3;
//        a4 -= d * ab.a4;
//        b -= d * ab.b;
//    }
//    public override string ToString()
//    {
//        return string.Format($"| {a1} | {a2} | {a3} | {a4} | {b} |");
//    }
//}
//protected double[] LocalO_A_Diag;
//protected double[] LocalN_A_Diag;
//protected double[] LocalO_b;
//protected double[] LocalN_b;
//protected int deltaALUIndex;//本地从0开始的index，相对于O_index
//MathTool.IfNullCreate(ref LocalO_A_Diag, O_Index.FaceIdx.GetCount());
//MathTool.IfNullCreate(ref LocalO_b, O_Index.FaceIdx.GetCount());
//MathTool.IfNullCreate(ref LocalN_A_Diag, N_Index.FaceIdx.GetCount());
//MathTool.IfNullCreate(ref LocalN_b, N_Index.FaceIdx.GetCount());
//if (Local_A_LU_Diff == null)
//{
//    Local_A_LU_Diff = new double[InnerIndex.FaceIdx.GetCount ()];
//}
//deltaALUIndex = -O_Index.FaceIdx.Start;
//TasksControl.AddDouble(ref N_A_Diag[nface.OwnerCellIndex], ngg);
//TasksControl.AddDouble(ref N_b[nface.OwnerCellIndex], nfacecor);
//TasksControl.AddDouble(ref O_A_Diag[oface.OwnerCellIndex], ogg);
//TasksControl.AddDouble(ref O_b[oface.OwnerCellIndex], ofacecor);
//public void Ini_Ab(int taskIndex)
//{
//    if (S is Value1Base s1)
//    {
//        if (s1 is Value1Const Stemp && Stemp.number == 0)
//        {
//            O_Index.CellIdx.GetSeg(out int i1, out int endp1, taskIndex);
//            for (; i1 < endp1; i1++)
//            {
//                O_b[i1] = 0;
//                O_A_Diag[i1] = 0;
//                int ncell = i1 + deltaCellIndex;
//                N_b[ncell] = 0;
//                N_A_Diag[ncell] = 0;
//            }
//        }
//        else
//        {
//            O_Index.FaceIdx.GetSeg(out int i1, out int endp1, taskIndex);
//            for (; i1 < endp1; i1++)
//            {
//                ref Face oface = ref O_faces[i1];
//                double s = s1.getFaceValue(i1) * oface.Area / 2;
//                O_b[oface.NeighborCellIndex] = s;
//                O_A_Diag[oface.NeighborCellIndex] = 0;
//                int ncell = oface.NeighborCellIndex + deltaCellIndex;
//                N_b[ncell] = s;
//                N_A_Diag[ncell] = 0;
//            }
//        }
//    }
//    else
//    {
//        throw new NotImplementedException();
//    }

//}

//public void Cal_Ab(int taskIndex)
//{
//    O_Index.FaceIdx.GetSeg(out int i1, out int endp1, taskIndex);
//    for (; i1 < endp1; i1++)
//    {
//        ref Face oface = ref O_faces[i1];
//        double ogamma = O_Gamma.getFaceValue(i1);
//        double ogg = ogamma * oface.gDiff;
//        double ofacecor = ogamma * oface.calNonOrthogonalityCorrection_bound(out double ocor_a, out double ocor_b, O_grad, O_x, O_cells);
//        ocor_a *= ogamma;
//        ocor_b *= ogamma;
//        O_A_LU[i1] = -ogg;
//        TasksControl.AddDouble(ref O_A_Diag[oface.OwnerCellIndex], ogg);
//        TasksControl.AddDouble(ref O_b[oface.OwnerCellIndex], ofacecor);
//        O_b[oface.NeighborCellIndex] -= ocor_b;

//        int nfidx = i1 + deltaFaceIndex;
//        ref Face nface = ref N_faces[nfidx];
//        double ngamma = N_Gamma.getFaceValue(nfidx);
//        double ngg = ngamma * nface.gDiff;
//        double nfacecor = ngamma * nface.calNonOrthogonalityCorrection_bound(out double ncor_a, out double ncor_b, N_grad, N_x, N_cells);
//        ncor_a *= ngamma;
//        ncor_b *= ngamma;
//        N_A_LU[nfidx] = -ngg;
//        TasksControl.AddDouble(ref N_A_Diag[nface.OwnerCellIndex], ngg);
//        TasksControl.AddDouble(ref N_b[nface.OwnerCellIndex], nfacecor);
//        N_b[nface.NeighborCellIndex] -= ncor_b;
//        double igg = Tau.getFaceValue(i1) * O_faces[i1].Area / Thickness.getFaceValue(i1);
//        A_LU_Diff[i1 + deltaALUIndex] = -igg;
//        O_A_Diag[oface.NeighborCellIndex] += ogg + igg + ocor_a;
//        N_A_Diag[nface.NeighborCellIndex] += ngg + igg + ncor_a;
//    }
//}
//O_Index.FaceIdx.GetSeg(out int oface, out int endp1, taskIndex);
//for (; oface < endp1; oface++)
//{
//    int ocell = O_faces[oface].NeighborCellIndex;
//    int nface = oface + deltaFaceIndex;
//    int ncell = ocell + deltaCellIndex;
//    double alu = A_LU_Diff[oface + deltaALUIndex];
//    O_x[ocell] = (O_b[ocell]
//        - O_A_LU[oface] * O_x[O_faces[oface].OwnerCellIndex]
//        - alu * N_x[ncell]
//        ) / O_A_Diag[ocell];
//    N_x[ncell] = (N_b[ncell]
//         - N_A_LU[nface] * N_x[N_faces[nface].OwnerCellIndex]
//         - alu * O_x[ocell]
//          ) / N_A_Diag[ncell];
//}
//O_Index.FaceIdx.GetSeg(out int i1, out int endp1, taskIndex);
//for (; i1 < endp1; i1++)
//{
//    ref Face oface = ref O_faces[i1];
//    double ogamma = O_Gamma.getFaceValue(i1);
//    double ogg = ogamma * oface.gDiff;
//    double ofacecor = ogamma * oface.calNonOrthogonalityCorrection_bound(out double ocor_a, out double ocor_b, O_grad, O_x, O_cells);
//    ocor_a *= ogamma;
//    ocor_b *= ogamma;
//    O_A_LU[i1] = -ogg;
//    O_bFaceCommon[i1] = ofacecor;
//    //TasksControl.AddDouble(ref O_A_Diag[oface.OwnerCellIndex], ogg);
//    //TasksControl.AddDouble(ref O_b[oface.OwnerCellIndex], ofacecor);

//    int nfidx = i1 + deltaFaceIndex;
//    ref Face nface = ref N_faces[nfidx];
//    double ngamma = N_Gamma.getFaceValue(nfidx);
//    double ngg = ngamma * nface.gDiff;
//    double nfacecor = ngamma * nface.calNonOrthogonalityCorrection_bound(out double ncor_a, out double ncor_b, N_grad, N_x, N_cells);
//    ncor_a *= ngamma;
//    ncor_b *= ngamma;
//    N_A_LU[nfidx] = -ngg;
//    N_bFaceCommon[i1] = nfacecor;
//    //TasksControl.AddDouble(ref N_A_Diag[nface.OwnerCellIndex], ngg);
//    //TasksControl.AddDouble(ref N_b[nface.OwnerCellIndex], nfacecor);

//    //O_A_Diag[oface.NeighborCellIndex] += ogg + ngg;
//    //O_b[oface.NeighborCellIndex] -= ofacecor + nfacecor;
//    O_A_Diag[oface.NeighborCellIndex] = ogg + ngg + ocor_a + ncor_a;//一次成型
//    O_b[oface.NeighborCellIndex] = -(ocor_b + ncor_b);
//}

//switch (Tau.valueState)
//{
//    case ValueStates.每次都算:
//        set_A_lu(taskIndex);
//        break;
//    case ValueStates.算一次_未计算:
//        set_A_lu(taskIndex);
//        TasksControl.Sync(taskIndex, Tau.setStateUsed);
//        break;
//    case ValueStates.算一次_已计算:
//        break;
//}
//protected void set_A_lu(int taskIndex)
//{
//    O_Index.getFaceSection(out int i1, out int endp1, taskIndex);
//    int deltaFace = -O_Index.StartFaceIndex;
//    for (; i1 < endp1; i1++)
//    {
//        A_LU_Diff[i1 + deltaFace] = -Tau.getFaceValue(i1) * O_faces[i1].Area / Thickness.getFaceValue(i1);
//    }
//}
//public void Set_A_Diag(int taskIndex)
//{
//    O_Index.getFaceSection(out int i1, out int endp1, taskIndex);
//    int deltaFace = -O_Index.StartFaceIndex;
//    for (; i1 < endp1; i1++)
//    {
//        double facediff = A_LU_Diff[i1 + deltaFace];
//        O_A_Diag[O_faces[i1].NeighborCellIndex] = -O_A_LU[i1] - facediff;
//        int neighborface = i1 + deltaFaceIndex;
//        N_A_Diag[N_faces[neighborface].NeighborCellIndex] = -N_A_LU[neighborface] - facediff;
//    }
//}

//public void Correct(int taskIndex)
//{
//    O_Index.getFaceSection(out int i1, out int endp1, taskIndex);
//    for (; i1 < endp1; i1++)
//    {
//        O_b[O_faces[i1].NeighborCellIndex] -= O_faceCommon[i1];
//        int neighborface = i1 + deltaFaceIndex;
//        N_b[N_faces[neighborface].NeighborCellIndex] -= N_faceCommon[neighborface];
//    }
//}
//protected void cal_x(int oface)
//{
//    int ocell = O_faces[oface].NeighborCellIndex;
//    int nface = oface + deltaFaceIndex;
//    int ncell = ocell + deltaCellIndex;
//    double alu = A_LU_Diff[oface + deltaALUIndex];
//    O_x[ocell] = (O_b[ocell]
//        - O_A_LU[oface] * O_x[O_faces[oface].OwnerCellIndex]
//        - alu * N_x[ncell]
//        ) / O_A_Diag[ocell];

//    N_x[ncell] = (N_b[ncell]
//         - N_A_LU[nface] * N_x[N_faces[nface].OwnerCellIndex]
//         - alu * O_x[ocell]
//          ) / N_A_Diag[ncell];
//}
//protected void set_b_2_value(ref Face face, int faceIndex)
//{
//    double s = S.getFaceValue(faceIndex) * face.Area / 2;
//    b_owner[face.NeighborCellIndex] = s;
//    b_neighbor[face.NeighborCellIndex + deltaCellIndex] = s;
//}
//public void Cal_x_Jacobi_Step1(int taskIndex)
//{
//    cal_x(x_owner, x_neighbor, x_OwnerCommon, x_NeighborCommon, taskIndex);
//}
//public void Cal_x_Jacobi_Step2(int taskIndex)
//{
//    cal_x(x_OwnerCommon, x_NeighborCommon, x_owner, x_neighbor, taskIndex);
//}

//protected void cal_x(double[] fromArray_O, double[] fromArray_N, double[] toArray_O, double[] toArray_N, int taskIndex)
//{
//    int oface, endp1;
//    OwnerIndex.getFaceSection(out oface, out endp1, taskIndex);
//    int deltaFace = -OwnerIndex.StartFaceIndex;
//    for (; oface < endp1; oface++)
//    {
//        int ocell = faces_owner[oface].NeighborCellIndex;
//        int nface = oface + deltaFaceIndex;
//        int ncell = ocell + deltaCellIndex;
//        toArray_O[ocell] = (b_owner[ocell]
//            - A_LU_owner[oface] * fromArray_O[faces_owner[oface].OwnerCellIndex]
//            - A_LU_Diff[oface + deltaFace] * fromArray_N[ncell]
//            ) / A_Diag_owner[ocell];

//        toArray_N[ncell] = (b_neighbor[ncell]
//             - A_LU_neighbor[nface] * fromArray_N[faces_neighbor[nface].OwnerCellIndex]
//             - A_LU_Diff[oface + deltaFace] * fromArray_O[ocell]
//              ) / A_Diag_neighbor[ncell];
//    }
//}
//this.O_x = ownerScalar.x;
//this.O_A_Diag = ownerScalar.A_Diag;
//this.O_A_LU = ownerScalar.A_LU_Diff;
//this.O_b = ownerScalar.b;
//this.N_x = neighborScalar.x;
//this.N_A_Diag = neighborScalar.A_Diag;
//this.N_A_LU = neighborScalar.A_LU_Diff;
//this.N_b = neighborScalar.b;
//public void pass_x_e_ToCoarser(out double[] e_ownerfine, out double[] e_neighborfine)
//{
//    e_ownerfine = this.x_owner;
//    e_neighborfine = this.x_neighbor;
//}
//public void pass_A_LU_owner_ToCoarser(out double A_lu_owner, ref CoarseFace ownerCoarser)
//{
//    double aluo = 0;
//    foreach (int fineface in ownerCoarser.FineFaces_O2N)
//    {
//        aluo += A_LU_owner[fineface];
//    }
//    A_lu_owner = aluo;
//}

//public void pass_A_LU_neighbor_ToCoarser(out double A_lu_neighbor, ref CoarseFace neighborCoarser)
//{
//    double alu = 0;
//    foreach (int fineface in neighborCoarser.FineFaces_O2N)
//    {
//        alu += A_LU_neighbor[fineface];
//    }
//    A_lu_neighbor = alu;
//}
//protected void set_b_value_owner(ValueBase value, IndexNumber indexNumber, int taskIndex)
//{
//    int i1, endp1;
//    indexNumber.getFaceInterval(out i1, out endp1, taskIndex);
//    for (; i1 < endp1; i1++)
//    {
//        b_owner[faces_owner[i1].NeighborCellIndex] = value.getFaceValue(i1) * faces_owner[i1].Normal.Length;
//    }
//}

//public void pass_A_r_ToCoarser(out double A, ref CoarseCell ownerCoarseCell)
//{
//    double Atemp = 0;
//    double rtemp = 0;
//    foreach (int finecell in ownerCoarseCell.FineCells)
//    {
//        double atemp = A_Diag_owner[finecell];
//        Atemp += atemp;
//        rtemp += b_owner[finecell]
//            - cells_owner[finecell].calALUProductValue(faces_owner, A_LU_owner, x_owner)
//            - cells_neighbor[finecell + IndexOfN_O].calALUProductValue(faces_neighbor, A_LU_neighbor, x_neighbor);
//    }
//    A = Atemp;
//    ownerCoarseCell.r  = rtemp;
//}

//public void pass_A_LU_ToCoarser(out double A_lu_owner,out double A_lu_neighbor, ref CoarseFace ownerCoarseFace)
//{
//    double aluo = 0;
//    double alun = 0;
//    foreach (int fineface in ownerCoarseFace.FineFaces_O2N)
//    {
//        aluo += A_LU_owner[fineface];
//        alun += A_LU_neighbor[fineface + IndexOfN_O];
//    }
//    A_lu_owner = aluo;
//    A_lu_neighbor = alun;
//}